package com.example.chatweb.utils;

import com.alibaba.fastjson.JSONObject;
import java.io.File;
import java.io.IOException;
import java.net.URI;
import java.util.Map;
import java.util.Objects;
import java.util.Set;
import org.apache.commons.io.FileUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.io.ByteArrayResource;
import org.springframework.core.io.FileSystemResource;
import org.springframework.http.HttpEntity;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Component;
import org.springframework.util.LinkedMultiValueMap;
import org.springframework.util.MultiValueMap;
import org.springframework.web.client.RestTemplate;
import org.springframework.web.multipart.MultipartFile;
import org.springframework.web.server.ResponseStatusException;
import org.springframework.web.util.UriComponentsBuilder;

/**
 * <h3>chat-web</h3>
 *
 * @author HuangJiayu
 * @description <p>HTTP工具类</p>
 * @date 2024-04-05 12:25
 * @note restTemplate方式直接传入字符串具有编码问题，应该自己将String类型直接转换为URI类型(尤其是下载文件的)
 **/

// 使用方式是依赖注入
@Component
public class HttpUtil {

	@Autowired
	private RestTemplate restTemplate;

	/**
	 * @param url:    访问地址
	 * @param params: 请求参数，前面是key，后面是value
	 * @return JSONObject: 通过JSONObject.getXX(key)获取value
	 * @date :2024/4/5 14:44
	 * @description : 发送post请求，该重载方法用于发送json格式的请求，适用于灵活添加参数，通过HashMap类型添加键值对，可以是数组等多种复杂类型
	 */

	public JSONObject post(String url, Map<String, Object> params) {
		HttpHeaders headers = new HttpHeaders();
		headers.setContentType(MediaType.APPLICATION_JSON);
		HttpEntity<Map<String, Object>> request = new HttpEntity<>(params, headers);
		ResponseEntity<JSONObject> response = restTemplate.postForEntity(url, request,
		 JSONObject.class);
		if (response.getStatusCode() != HttpStatus.OK) {
			throw new ResponseStatusException(response.getStatusCode(), "请求出错");
		}
		return response.getBody();
	}

	/**
	 * @param url:    访问地址
	 * @param params: 请求参数，需要是一个Object类的对象，自己定义好成员属性
	 * @description 发送post请求，该重载方法用于已经装好的请求体，直接传入对应的对象类型即可，没有上面灵活，适用于和数据库相关的实体
	 */

	public <T> JSONObject post(String url, T params) {
		HttpHeaders headers = new HttpHeaders();
		headers.setContentType(MediaType.APPLICATION_JSON);
		HttpEntity<T> request = new HttpEntity<>(params, headers);
		ResponseEntity<JSONObject> response = restTemplate.postForEntity(url, request,
		 JSONObject.class);
		if (response.getStatusCode() != HttpStatus.OK) {
			throw new ResponseStatusException(response.getStatusCode(), "请求出错");
		}
		return response.getBody();
	}

	/**
	 * @param url: 访问地址
	 * @description 发送get请求，该重载方法用于已经装好的请求体，直接传入对应的对象类型即可，传回的是文件二进制流，用于PDF文件的传输
	 */
	public <T> byte[] getFile(String url) {
		URI uri = URI.create(url);
		ResponseEntity<byte[]> response = restTemplate.getForEntity(uri, byte[].class);
		if (response.getStatusCode() != HttpStatus.OK) {
			throw new ResponseStatusException(response.getStatusCode(), "请求出错");
		}
		return response.getBody();
	}

	public MultipartFile postFile(String url, byte[] file) {
		URI uri = URI.create(url);
		HttpHeaders headers = new HttpHeaders();
		headers.setContentType(MediaType.APPLICATION_OCTET_STREAM);
		HttpEntity<byte[]> request = new HttpEntity<>(file, headers);
		ResponseEntity<MultipartFile> response = restTemplate.postForEntity(uri, request,
		 MultipartFile.class);
		if (response.getStatusCode() != HttpStatus.OK) {
			throw new ResponseStatusException(response.getStatusCode(), "请求出错");
		}
		return response.getBody();
	}

	public byte[] postFile(String url, MultipartFile multipartFile) {
		URI uri = URI.create(url);
		File file = new File("./test1.pdf");
		try {
			FileUtils.copyInputStreamToFile(multipartFile.getInputStream(), file);
			FileSystemResource resource = new FileSystemResource(file);
			// note: restTemplate 默认就是form-data格式上传
			MultiValueMap<String, Object> params = new LinkedMultiValueMap<>();
			params.add("file", resource);
			ResponseEntity<byte[]> response = restTemplate.postForEntity(uri, params, byte[].class);
			if (response.getStatusCode() != HttpStatus.OK) {
				throw new ResponseStatusException(response.getStatusCode(), "请求出错");
			}
			return response.getBody();
		} catch (IOException e) {
			throw new MyExceptionHandler("文件转换失败");
		}
	}

	/**
	 * 描述:fileName 带有后缀
	 */

	public JSONObject postFileAndFormData(String url, byte[] file, String fileName,
	 Map<String, Object> fromData) {
		URI uri = URI.create(url);
		HttpHeaders headers = new HttpHeaders();
		headers.setContentType(MediaType.MULTIPART_FORM_DATA);

		// 构造请求体
		MultiValueMap<String, Object> params = new LinkedMultiValueMap<>();
		params.add("files", new ByteArrayResource(file) {
			@Override
			public String getFilename() {
				return fileName;
			}
		});
		// 追加额外表单数据
		Set<String> keySet = fromData.keySet();
		for (String key : keySet) {
			params.add(key, fromData.get(key));
		}

		// 创建 HTTP 实体
		HttpEntity<MultiValueMap<String, Object>> requestEntity = new HttpEntity<>(params, headers);

		// 发送 POST 请求
		ResponseEntity<JSONObject> response = restTemplate.postForEntity(uri, requestEntity,
		 JSONObject.class);

		// 处理响应
		if (response.getStatusCode() != HttpStatus.OK) {
			throw new ResponseStatusException(response.getStatusCode(), "请求出错");
		}

		return response.getBody();
	}

	public JSONObject get(String url, Map<String, Object> params) {
		//	拼接url
		UriComponentsBuilder builder = UriComponentsBuilder.fromHttpUrl(url);
		// 类型转换将Map变为MultiValueMap
		MultiValueMap<String, String> multiValueMap = new LinkedMultiValueMap<>();
		if (params != null) {
			params.forEach((key, value) -> multiValueMap.add(key, value.toString()));
		}
		URI uri = builder.queryParams(multiValueMap).build().encode().toUri();

		ResponseEntity<JSONObject> response = restTemplate.getForEntity(uri, JSONObject.class);

		if (response.getStatusCode() != HttpStatus.OK) {
			throw new ResponseStatusException(response.getStatusCode(), "请求出错");
		}
		return response.getBody();
	}

	public JSONObject postFileGetJSON(String url, MultipartFile multipartFile) {
//		这个名字可以变为传入的名字，使用 multipartFile.getFilename 自己查询
		File file = new File(Objects.requireNonNull(multipartFile.getOriginalFilename()));
		try {
			FileUtils.copyInputStreamToFile(multipartFile.getInputStream(), file);
			FileSystemResource resource = new FileSystemResource(file);
			// note: restTemplate 默认就是form-data格式上传
			MultiValueMap<String, Object> params = new LinkedMultiValueMap<>();
			params.add("file", resource);
			ResponseEntity<JSONObject> response = restTemplate.postForEntity(url, params,
					JSONObject.class);
			if (response.getStatusCode() != HttpStatus.OK) {
				throw new ResponseStatusException(response.getStatusCode(), "请求出错");
			}
			return response.getBody();
		} catch (IOException e) {
			throw new MyExceptionHandler("文件转换失败");
		}
	}

}
